#pragma once

#include <osgDB/ReadFile>
#include <osg/Referenced>
#include "corebase_global.h"
#include <osg/Group>
#include <osgAnimation/AnimationManagerBase>
#include <osg/FrameStamp>
#include <osgAnimation\Animation>
#include <QString>

namespace CoreBase
{
	class COREBASE_EXPORT AnimationManager : public osgAnimation::AnimationManagerBase
	{
	public:
		AnimationManager();
		AnimationManager(const AnimationManagerBase& b, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY); 
		class InAnimation:public osg::Referenced
		{
		public:
			InAnimation();
			void setBindOsgAnimation(osgAnimation::Animation* ani);
			osg::ref_ptr<osgAnimation::Animation> getBindOsgAnimation();
			void setStartOff(float offset);
			void setLoopTimes(int times);
			bool updataAnimation(float time, int priority = 0);
			void setStartTime(float time)  { _startTime = time;}
			float getStartTime() const { return _startTime;}
			void setDuration(double duration)
			{
				_duration = duration;
				_originalDuration = computeDurationFromChannels();
			}
			void resetTargets()
			{
				_bindOsgAnimation->resetTargets();
			}
			double computeDurationFromChannels() const;
			void computeDefaultDuration();
			void setWeight(float weight)
			{
				_weight = weight;
			}
		protected:
			~InAnimation();
			float										_startTimeOff;
			int											_loopTimes;
			osg::ref_ptr<osgAnimation::Animation>		_bindOsgAnimation;
			float										_startTime;
			double										_duration;
			double										_originalDuration;
			QString										_animationName;
			float										_weight;
		};

		void update (double time,int priority);
		void update(double t);
		void playAnimation ();
		void playAnimation (float starttime,float duration,int looptimes = 1,int priority = 0, float weight = 1.0);
		void stopAnimation ();
		bool isPlaying ();
	protected:
		virtual ~AnimationManager();
		typedef std::vector<osg::ref_ptr<InAnimation>> InAnimationVector;
		InAnimationVector _animationsPlaying;
		double _lastUpdate;
	};

	struct AnimationManagerFinder : public osg::NodeVisitor
	{
		osg::ref_ptr<osgAnimation::AnimationManagerBase>	_am;
		AnimationManagerFinder() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
		void apply(osg::Node& node) {
			if (_am.valid())
				return;
			if (node.getUpdateCallback()) {
				osgAnimation::AnimationManagerBase* b = dynamic_cast<osgAnimation::AnimationManagerBase*>(node.getUpdateCallback());
				if (b) {
					_am = new AnimationManager(*b);
					return;
				}
			}
			traverse(node);
		}
	};

	class COREBASE_EXPORT FbxAnimationControl:public osg::Referenced
	{
	public:
		FbxAnimationControl();
		bool play(const QString& managerid,float starttime,float endtime,float nlooptimes);
		bool stop(const QString& managerid);  
		void stopAll();
		void Clear();
		bool havefbxAnimationCallback(osg::Node* pNode);
		bool registerAnimationCallback(const QString& deviceid,osg::Node* pNode);
	private:
		std::map<QString,osg::ref_ptr<osgAnimation::AnimationManagerBase>>		_map;
	protected:
		~FbxAnimationControl(){}
	};
}